home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / newsrc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-22  |  10.1 KB  |  424 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record (rhr@clio.rice.edu)
  3.  * 
  4.  * This file is part of ED.
  5.  * 
  6.  * ED is free software; you can redistribute it and/or modify it under the terms
  7.  * of the GNU General Public License as published by the Free Software Foundation.
  8.  * 
  9.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  10.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  12.  * 
  13.  * You should have received a copy of the GNU General Public License along with ED
  14.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  15.  * Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "opsys.h"
  18.  
  19. #ifndef NO_NEWS
  20.  
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24.  
  25. #include "memory.h"
  26. #include "ctyp_dec.h"
  27. #include "rec.h"
  28. #include "window.h"
  29. #include "ed_dec.h"    /* global data */
  30. #include "buffer.h"
  31. #include "buf_dec.h"    /* kill buffers */
  32. #include "cmd_enum.h"
  33. #include "handy.h"    /* for definition of max() */
  34. #include "keyvals.h"    /* for numeric values corresponding to editor commands */
  35. #include "file.h"
  36.  
  37. static rec_ptr netrc_rec = NULL;    /* this gets the NETRC entry when they select a group */
  38. static Int *first,*last,pairs = 0,allocated = 0;
  39.  
  40. /******************************************************************************\
  41. |Routine: newsrc_encode
  42. |Callby: newsrc_mark_read newsrc_mark_unread
  43. |Purpose: Formats read-article list into NETRC entry.
  44. |Arguments:
  45. |    none
  46. \******************************************************************************/
  47. void newsrc_encode()
  48. {
  49.     Int groupl,count,i;
  50.     Char numbuf[32],*p,*buf;
  51.     
  52.     groupl = count = strchr(netrc_rec->data,' ') - netrc_rec->data + 1;
  53.     for(i = 0;i < pairs;i++)
  54.     {
  55.         if(first[i] == last[i])
  56.         {
  57.             sprintf(numbuf,"%d,",first[i]);
  58.             count += strlen(numbuf);
  59.         }
  60.         else
  61.         {
  62.             sprintf(numbuf,"%d-%d,",first[i],last[i]);
  63.             count += strlen(numbuf);
  64.         }
  65.     }
  66.     buf = (Char *)imalloc(count + 1);
  67.     memcpy(buf,netrc_rec->data,groupl);
  68.     for(p = buf + groupl,i = 0;i < pairs;i++)
  69.         if(first[i] == last[i])
  70.         {
  71.             sprintf(p,"%d,",first[i]);
  72.             p += strlen(p);
  73.         }
  74.         else
  75.         {
  76.             sprintf(p,"%d-%d,",first[i],last[i]);
  77.             p += strlen(p);
  78.         }
  79.     if(pairs)
  80.         *--p = '\0';    /* trim the last comma */
  81.     else
  82.         *p = '\0';
  83.     ifree(netrc_rec->data);
  84.     netrc_rec->data = buf;
  85. }
  86.  
  87. /******************************************************************************\
  88. |Routine: newsrc_make_room
  89. |Callby: newsrc_mark_read newsrc_mark_unread
  90. |Purpose: Insures we have enough room for a given number of pairs.
  91. |Arguments:
  92. |    n is the number of pairs required.
  93. \******************************************************************************/
  94. void newsrc_make_room(n)
  95. Int n;
  96. {
  97.     Int *nf,*nl;
  98.     
  99.     if(n > allocated)
  100.     {
  101.         nf = (Int *)imalloc((pairs + 1) * sizeof(Int));
  102.         nl = (Int *)imalloc((pairs + 1) * sizeof(Int));
  103.         if(pairs)
  104.         {
  105.             memcpy(nf,first,pairs * sizeof(Int));
  106.             memcpy(nl,last,pairs * sizeof(Int));
  107.         }
  108.         if(first)
  109.             ifree(first);
  110.         if(last)
  111.             ifree(last);
  112.         first = nf;
  113.         last = nl;
  114.         allocated = n;
  115.     }
  116. }
  117.  
  118. /******************************************************************************\
  119. |Routine: newsrc_low
  120. |Callby: news_group
  121. |Purpose: Marks article 1 through article low-1 as read.
  122. |Arguments:
  123. |    low is the lowest-numbered article in the group (returned by GROUP).
  124. \******************************************************************************/
  125. void newsrc_low(low)
  126. Int low;
  127. {
  128.     Int i,j,k;
  129.     
  130.     if(!pairs)
  131.     {
  132.         newsrc_make_room(1);
  133.         first[0] = 1;
  134.         last[0] = low - 1;
  135.         pairs = 1;
  136.     }
  137.     else if(low == first[0])
  138.         first[0] = 1;
  139.     else if(low < first[0])
  140.     {
  141.         newsrc_make_room(pairs + 1);
  142.         for(i = pairs;i > 0;i--)
  143.         {
  144.             first[i] = first[i - 1];
  145.             last[i] = last[i - 1];
  146.         }
  147.         first[0] = 1;
  148.         last[0] = low - 1;
  149.         pairs++;
  150.     }
  151.     else
  152.     {
  153.         for(i = 0;i < pairs;i++)
  154.             if(first[i] >= low)
  155.                 break;
  156.         if(first[i] == low)
  157.             first[i] = 1;
  158.         else
  159.         {
  160.             first[i - 1] = 1;
  161.             last[i - 1] = low - 1;
  162.         }
  163.         if(i > 0)
  164.         {
  165.             for(j = i,k = 0;j < pairs;j++)
  166.             {
  167.                 first[k] = first[j];
  168.                 last[k++] = last[j];
  169.             }
  170.             pairs--;
  171.         }
  172.     }
  173.     newsrc_encode();
  174. }
  175.  
  176. /******************************************************************************\
  177. |Routine: newsrc_save
  178. |Callby: command
  179. |Purpose: Saves a new .newsrc.
  180. |Arguments:
  181. |    none
  182. \******************************************************************************/
  183. Int newsrc_save()
  184. {
  185.     Char fname[512],fname2[512],buf[512],*r;
  186.     rec_ptr p,q;
  187.     FILE *fp;
  188.     Int l;
  189.     
  190. #ifdef VMS
  191.     strcpy(fname,"sys$login:.newsrc-new");
  192.     strcpy(fname2,"sys$login:.newsrc");
  193. #else
  194.     strcpy(fname,"$HOME/.newsrc.new");
  195.     strcpy(fname2,"$HOME/.newsrc");
  196. #endif
  197.     envir_subs(fname);
  198.     envir_subs(fname2);
  199.     if(!(fp = fopen(fname,"w")))
  200.     {
  201.         slip_message("I am unable to create the file $HOME/.newsrc.new.");
  202.         wait_message();
  203.         return(0);
  204.     }
  205. /* examine all visible groups, checking for deletions */
  206.     for(p = WINDOW[0].base->next,q = NETRC->next;p != WINDOW[0].base;p = p->next)
  207.     {
  208.         r = p->data + groupname_offset();
  209.         l = strlen(r);    /* get the length of the group name */
  210.         while(strncmp(r,q->data,l))    /* advance to matching entry in newsrc database */
  211.             q = q->next;
  212.         if(p->recflags & 2)    /* this newsgroup has been marked for unsubscription, insure it's unsubscribed */
  213.         {
  214.             if((r = strchr(q->data,':')))
  215.                 *r = '!';
  216.         }
  217.         else    /* this newsgroup has been marked for subscription, insure it's subscribed */
  218.         {
  219.             if((r = strchr(q->data,'!')))
  220.                 *r = ':';
  221.         }
  222.     }
  223. /* load all the entries to the file */
  224.     for(q = NETRC->next;q != NETRC;q = q->next)
  225.         fprintf(fp,"%s\n",q->data);
  226.     fclose(fp);
  227. /* rename the new file to the old file */
  228.     if(rename(fname,fname2))
  229.     {
  230.         sprintf(buf,"I was unable to rename '%s' to '%s'. '%s' has your saved changes.",fname,fname2,fname);
  231.         wait_message();
  232.         return(0);
  233.     }
  234.     return(1);
  235. }
  236.  
  237. /******************************************************************************\
  238. |Routine: newsrc_current
  239. |Callby: command
  240. |Purpose: Sets the current NETRC pointer.
  241. |Arguments:
  242. |    group is the group name.
  243. \******************************************************************************/
  244. void newsrc_current(group)
  245. Char *group;
  246. {
  247.     rec_ptr p;
  248.     Char *sp;
  249.     Int n1,n2,*i1,*i2,l;
  250.     
  251. /* find the matching entry in the NETRC list */
  252.     l = strlen(group);
  253.     for(p = NETRC->next;p != NETRC;p = p->next)
  254.         if(!strncmp(p->data,group,l))
  255.             break;
  256.     netrc_rec = p;
  257. /* count the range pairs */
  258.     sp = netrc_rec->data;
  259.     for(pairs = 0;get_artnum(&sp,&n1,&n2);pairs++);
  260. /* reallocate memory */
  261.     if(pairs > allocated)
  262.     {
  263.         if(first)
  264.             ifree(first);
  265.         if(last)
  266.             ifree(last);
  267.         first = (Int *)imalloc(pairs * sizeof(Int));
  268.         last = (Int *)imalloc(pairs * sizeof(Int));
  269.         allocated = pairs;
  270.     }
  271. /* load the arrays */
  272.     sp = netrc_rec->data;
  273.     i1 = first;
  274.     i2 = last;
  275.     while(get_artnum(&sp,i1++,i2++));
  276. }
  277.  
  278. /******************************************************************************\
  279. |Routine: newsrc_unread
  280. |Callby: news_group
  281. |Purpose: Returns an indication of whether the given article has been read.
  282. |Arguments:
  283. |    article is the article number.
  284. \******************************************************************************/
  285. Int newsrc_unread(article)
  286. Int article;
  287. {
  288.     Int i;
  289.     
  290.     for(i = 0;i < pairs;i++)
  291.         if(article >= first[i] && article <= last[i])
  292.             return(0);
  293.     return(1);
  294. }
  295.  
  296. /******************************************************************************\
  297. |Routine: newsrc_mark_read
  298. |Callby: edit
  299. |Purpose: Modifies the current NETRC list to mark an article as read.
  300. |Arguments:
  301. |    article is the article number.
  302. \******************************************************************************/
  303. void newsrc_mark_read(article)
  304. Int article;
  305. {
  306.     Int i,j;
  307.     
  308.     for(i = 0;i < pairs;i++)
  309.     {
  310.         if(article >= first[i] && article <= last[i])
  311.             return;    /* the article is already marked as read?? */
  312.         if(article == first[i] - 1)    /* if the article is right before an existing pair, merge it */
  313.         {
  314.             first[i] = article;
  315.             if(i > 0)    /* if the current pair is now contiguous with its predecessor, merge it */
  316.                 if(last[i - 1] == first[i] - 1)
  317.                 {
  318.                     last[i - 1] = last[i];
  319.                     for(j = i + 1;j < pairs - 1;j++)
  320.                     {
  321.                         first[j] = first[j + 1];
  322.                         last[j] = last[j + 1];
  323.                     }
  324.                     pairs--;
  325.                 }
  326.             goto report;
  327.         }
  328.         if(article == last[i] + 1)
  329.         {
  330.             last[i] = article;
  331.             if(i < pairs - 1)
  332.                 if(last[i] == first[i + 1] - 1)
  333.                 {
  334.                     last[i] = last[i + 1];
  335.                     for(j = i + 1;j < pairs - 1;j++)
  336.                     {
  337.                         first[j] = first[j + 1];
  338.                         last[j] = last[j + 1];
  339.                     }
  340.                     pairs--;
  341.                 }
  342.             goto report;
  343.         }
  344.     }
  345. /* it doesn't match any existing range, it needs its own entry */
  346.     for(i = 0;i < pairs;i++)
  347.         if(first[i] > article)
  348.             break;
  349. /* insure we have room to insert an entry */
  350.     newsrc_make_room(pairs + 1);
  351.     if(i == pairs)
  352.         first[pairs] = last[pairs] = article;
  353.     else    /* the new one must be inserted into the list */
  354.     {
  355.         for(j = pairs;j > i;j--)    /* slide everyone over */
  356.         {
  357.             first[j] = first[j - 1];
  358.             last[j] = last[j - 1];
  359.         }
  360.         first[i] = last[i] = article;
  361.     }
  362.     pairs++;
  363. /* now encode the list into a buffer and replace it in the current NETRC record */
  364. report:
  365.     newsrc_encode();
  366. }
  367.  
  368. /******************************************************************************\
  369. |Routine: newsrc_mark_unread
  370. |Callby: edit
  371. |Purpose: Modifies the current NETRC list to mark an article as read.
  372. |Arguments:
  373. |    article is the article number.
  374. \******************************************************************************/
  375. void newsrc_mark_unread(article)
  376. Int article;
  377. {
  378.     Int i,j;
  379.     
  380.     for(i = 0;i < pairs;i++)
  381.     {
  382.         if(article > first[i] && article < last[i])    /* article is part of a range, split it */
  383.         {
  384.             newsrc_make_room(pairs + 1);
  385.             for(j = pairs;j > i;j--)
  386.             {
  387.                 first[j] = first[j - 1];
  388.                 last[j] = last[j - 1];
  389.             }
  390.             last[i] = article - 1;
  391.             first[i + 1] = article + 1;
  392.             pairs++;
  393.             goto report;
  394.         }
  395.         if(article == first[i])
  396.         {
  397.             if(article == last[i])
  398.             {
  399.                 for(j = i;j < pairs - 1;j++)
  400.                 {
  401.                     first[j] = first[j + 1];
  402.                     last[j] = last[j + 1];
  403.                 }
  404.                 pairs--;
  405.             }
  406.             else
  407.                 first[i] = article + 1;
  408.             goto report;
  409.         }
  410.         if(article == last[i])
  411.         {
  412.             last[i] = article - 1;
  413.             goto report;
  414.         }
  415.     }
  416. /* it isn't shown as read, ignore the request */
  417.     return;
  418. /* now encode the list into a buffer and replace it in the current NETRC record */
  419. report:
  420.     newsrc_encode();
  421. }
  422. #endif
  423.  
  424.